#include "output.h"
#include "src/color.h"
#include "src/vector3d.h"
#include "src/cuboidPrimitive.h"
#include "src/spherePrimitive.h"
#include "src/cylinderPrimitive.h"
#include "src/conePrimitive.h"
#include "src/combinedObject.h"
#include "defines/octreeType.h"
#include "defines/primitive.h"

#include <QDebug>
#include <QString>
#include <QFileInfo>
#include <iostream>

Output::Output(){
    file = NULL;
}

Output::~Output(){
}

void Output::parseObjects(QFile *_file, Scene *_s){
	Object *object;
    file = _file;

    file->open(QFile::WriteOnly);

	for(unsigned int i = 0; i < _s->getObjectsSize(); i++){
	    object = _s->getObject(i);
	    //cada linha representará um objeto
	    writeObject(object);
	}

    file->close();
}

void Output::parseObjects(Scene *_s){
	Object *object;

    file->open(QFile::WriteOnly);
	for(unsigned int i = 0; i < _s->getObjectsSize(); i++){
	    object = _s->getObject(i);
	    //cada linha representará um objeto
	    writeObject(object);
	}
    file->close();
}

void Output::writeObject(Object *_obj, int _parentId){
	QTextStream stream(file);

    int type = _obj->getType();
    int id = _obj->getId();
    Color c = _obj->getColor();
    int rotationX = _obj->getRotationX();
    int rotationY = _obj->getRotationY();
    int rotationZ = _obj->getRotationZ();

    if(_obj->isPrimitive()){
        stream << "p " << id << " " << type  << " " << _parentId //p de primitiva
                  << " " << c.red << " " << c.green << " " << c.blue << " " << c.alpha
                  << " " << rotationX << " " << rotationY << " " << rotationZ << " ";
        switch(type){
            case CUBOID:{
                Vector3D min = ((CuboidPrimitive *)_obj)->getPoint(0);
                Vector3D max = ((CuboidPrimitive *)_obj)->getPoint(7);
                stream << min.x << " " << min.y << " " << min.z << " " << max.x << " " << max.y << " " << max.z << endl;
                break;
            }
            case SPHERE:{
                Vector3D center = ((SpherePrimitive *)_obj)->getCenter();
                double radius = ((SpherePrimitive *)_obj)->getRadius();
                stream << center.x << " " << center.y << " " << center.z << " " << radius << endl;
                break;
            }
            case CYLINDER:{
                Vector3D center = ((CylinderPrimitive *)_obj)->getCenter();
                double radius = ((CylinderPrimitive *)_obj)->getRadius();
                double height = ((CylinderPrimitive *)_obj)->getHeight();
                stream << center.x << " " << center.y << " " << center.z << " " << radius << " " << height << endl;
                break;
            }
            case CONE:{
                Vector3D center = ((ConePrimitive *)_obj)->getCenter();
                double radius = ((ConePrimitive *)_obj)->getRadius();
                double height = ((ConePrimitive *)_obj)->getHeight();
                stream << center.x << " " << center.y << " " << center.z << " " << radius << " " << height << endl;
                break;
            }
        }

    }else{
        stream << "o " << id << " " << type  << " " << _parentId //p de primitiva
                  << " " << c.red << " " << c.green << " " << c.blue << " " << c.alpha
                  << " " << rotationX << " " << rotationY << " " << rotationZ << endl;
        for(unsigned int i = 0; i < ((CombinedObject *)_obj)->getObjectsSize(); i++){
            Object *obj = ((CombinedObject *)_obj)->getObject(i);
            writeObject(obj, id);
        }
    }
}

void Output::parseOctrees(QFile *_file, Scene *_s){
    _file->open(QFile::WriteOnly);

	for(unsigned int i = 0; i < _s->getOctreesSize(); i++){
	    Octree *octree = _s->getOctree(i);
	    //cada linha representará um objeto
        QTextStream stream(_file);
        Vector3D min = octree->getMin(), max = octree->getMax();
        Color color = octree->getObject()->getColor();
        stream << min.x << " " << min.y << " " << min.z << " " << max.x << " " << max.y << " " << max.z
               << color.red << color.green << color.blue << color.alpha << endl ;
	    writeNode(octree->getRoot(), _file);

        stream << endl;
	}
    _file->close();
}

void Output::writeNode(OctreeNode *_node, QFile *_file){
	QTextStream stream(_file);

    int type = _node->getType();

    switch(type){
        case WHITE:{
            stream << "W";
            stream.flush();
            break;
        }
        case BLACK:{
            stream << "B";
            stream.flush();
            break;
        }
        case GREY:{
            stream << "(";
            stream.flush();
            for(int i = 0; i < 8; i++)
                writeNode(_node->getNode(i), _file);
            break;
        }
    }
}

bool Output::isFileNull(){
    if(file) return false;
    return true;
}

void Output::setFile(QFile *_file){
    file = _file;
}
